/**
 * 轮播图组件的配置选项接口
 * 定义了轮播图的所有可配置参数
 */
interface CarouselOptions {
  container: string; // 轮播图容器选择器
  items: string; // 轮播项选择器
  autoPlay?: boolean; // 是否自动播放，默认true
  interval?: number; // 播放间隔(ms)，默认3000
  showDots?: boolean; // 是否显示指示器，默认true
  showArrows?: boolean; // 是否显示箭头，默认true
  transitionDuration?: number; // 动画时长(ms)，默认500
}

/**
 * 轮播图主类
 * 负责管理轮播图的整个生命周期，包括初始化、播放控制、事件绑定等
 */
class CarouselChart {
  /** 轮播图容器DOM元素 */
  private container: HTMLElement | null;
  /** 所有轮播项DOM元素的集合 */
  private items: NodeListOf<Element>;
  /** 当前显示的轮播项索引，从0开始计数 */
  private currentIndex: number = 0;
  /** 自动播放定时器ID，用于控制自动播放的启动和停止 */
  private timer: number | null = null;
  /** 轮播图的配置选项 */
  private options: CarouselOptions;
  /** 轮播图包装器，用于实现无限滚动效果 */
  private wrapper: HTMLElement | null = null;
  /** 图片总数量 */
  private totalItems: number = 0;
  /** 是否正在执行动画，防止快速点击导致的问题 */
  private isAnimating: boolean = false;
  /** 包装器宽度百分比 */
  private wrapperWidthPercent: number = 0;

  /**
   * 构造函数
   * @param options 轮播图配置选项
   */
  constructor(options: CarouselOptions) {
    // 合并用户配置和默认配置
    this.options = {
      autoPlay: true, // 默认启用自动播放
      interval: 3000, // 默认3秒切换一次
      showDots: true, // 默认显示指示器
      showArrows: true, // 默认显示箭头
      transitionDuration: 500, // 默认动画时长500ms
      ...options, // 用户自定义配置会覆盖默认值
    };

    // 获取DOM元素
    this.container = document.querySelector(this.options.container);
    this.items = document.querySelectorAll(this.options.items);

    // 验证DOM元素是否存在
    if (!this.container || this.items.length === 0) {
      console.error("轮播图初始化失败：容器或轮播项未找到");
      return;
    }

    this.totalItems = this.items.length;
    // 计算包装器宽度百分比
    this.wrapperWidthPercent = (this.totalItems + 1) * 100;
    // 开始初始化
    this.init();
  }

  /**
   * 初始化轮播图
   * 设置样式、创建UI元素、绑定事件、启动自动播放
   */
  private init(): void {
    this.setupStyles();
    this.createWrapper();
    if (this.options.showDots) this.createDots();
    if (this.options.showArrows) this.createArrows();
    this.bindEvents();
    if (this.options.autoPlay) this.startAutoPlay();
  }

  /**
   * 创建轮播图包装器，实现无限滚动效果
   */
  private createWrapper(): void {
    if (!this.container) return;

    this.wrapper = document.createElement("div");
    this.wrapper.className = "carousel-wrapper";
    this.wrapper.style.cssText = `
      position: absolute;
      top: 0;
      left: 0;
      width: ${this.wrapperWidthPercent}%;
      height: 100%;
      display: flex;
      transition: transform ${this.options.transitionDuration}ms ease-in-out;
    `;

    // 克隆并添加所有轮播项
    const itemWidth = (100 / this.wrapperWidthPercent) * 100;
    this.items.forEach((item) => {
      const clonedItem = item.cloneNode(true) as HTMLElement;
      clonedItem.style.width = `${itemWidth}%`;
      clonedItem.style.flexShrink = "0";
      this.wrapper!.appendChild(clonedItem);
    });

    // 添加第一项的副本实现无缝循环
    const firstItemClone = this.items[0].cloneNode(true) as HTMLElement;
    firstItemClone.style.width = `${itemWidth}%`;
    firstItemClone.style.flexShrink = "0";
    this.wrapper.appendChild(firstItemClone);

    this.container.appendChild(this.wrapper);
  }

  /**
   * 设置轮播图基础样式
   */
  private setupStyles(): void {
    if (this.container) {
      this.container.style.position = "relative";
      this.container.style.overflow = "hidden";
    }
  }

  /**
   * 创建底部指示器圆点
   */
  private createDots(): void {
    if (!this.options.showDots || !this.container) return;

    const dotsContainer = document.createElement("div");
    dotsContainer.className = "carousel-dots";
    dotsContainer.style.cssText = `
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 10px;
      z-index: 10;
    `;

    for (let i = 0; i < this.totalItems; i++) {
      const dot = document.createElement("span");
      dot.className = "carousel-dot";
      dot.style.cssText = `
        width: 12px;
        height: 12px;
        border-radius: 50%;
        background-color: ${i === 0 ? "#fff" : "rgba(255, 255, 255, 0.5)"};
        cursor: pointer;
        transition: background-color 0.3s;
      `;
      dot.addEventListener("click", () => this.goToSlide(i));
      dotsContainer.appendChild(dot);
    }

    this.container.appendChild(dotsContainer);
  }

  /**
   * 创建左右切换箭头
   */
  private createArrows(): void {
    if (!this.options.showArrows || !this.container) return;

    const createArrow = (isPrev: boolean) => {
      const arrow = document.createElement("div");
      arrow.innerHTML = isPrev ? "&#8249;" : "&#8250;";
      arrow.className = `carousel-arrow ${isPrev ? "prev" : "next"}`;
      arrow.style.cssText = `
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        ${isPrev ? "left: 20px" : "right: 20px"};
        width: 50px;
        height: 50px;
        background-color: rgba(0, 0, 0, 0.4);
        color: white;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 30px;
        cursor: pointer;
        border-radius: 50%;
        z-index: 10;
        transition: background-color 0.3s;
        line-height: 1;
      `;

      arrow.addEventListener("mouseenter", () => {
        arrow.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
      });

      arrow.addEventListener("mouseleave", () => {
        arrow.style.backgroundColor = "rgba(0, 0, 0, 0.4)";
      });

      arrow.addEventListener("click", () => {
        isPrev ? this.prev() : this.next();
      });

      return arrow;
    };

    this.container.appendChild(createArrow(true));
    this.container.appendChild(createArrow(false));
  }

  /**
   * 绑定轮播图事件监听器
   */
  private bindEvents(): void {
    this.container?.addEventListener("mouseenter", () => {
      if (this.options.autoPlay) this.stopAutoPlay();
    });

    this.container?.addEventListener("mouseleave", () => {
      if (this.options.autoPlay) this.startAutoPlay();
    });

    this.wrapper?.addEventListener("transitionend", () => {
      this.isAnimating = false;

      // 处理无缝循环
      if (this.currentIndex === this.totalItems) {
        this.wrapper!.style.transition = "none";
        this.wrapper!.style.transform = `translateX(0)`;
        this.currentIndex = 0;
        void this.wrapper!.offsetWidth; // 强制重排
        this.wrapper!.style.transition = `transform ${this.options.transitionDuration}ms ease-in-out`;
        this.updateDots(this.currentIndex);
      }
    });
  }

  /**
   * 切换到指定轮播项
   * @param index 目标轮播项的索引
   */
  private goToSlide(index: number): void {
    if (
      this.isAnimating ||
      index < 0 ||
      index > this.totalItems ||
      !this.wrapper
    )
      return;

    this.isAnimating = true;
    const moveDistance = -(index * ((100 / this.wrapperWidthPercent) * 100));
    this.wrapper.style.transform = `translateX(${moveDistance}%)`;

    if (index < this.totalItems) this.updateDots(index);
    this.currentIndex = index;
  }

  /**
   * 更新指示器圆点状态
   * @param index 当前显示的轮播项索引
   */
  private updateDots(index: number): void {
    const dots = this.container?.querySelectorAll(".carousel-dot");
    dots?.forEach((dot, i) => {
      (dot as HTMLElement).style.backgroundColor =
        i === index ? "#fff" : "rgba(255, 255, 255, 0.5)";
    });
  }

  /**
   * 切换到下一张轮播项
   */
  public next(): void {
    this.goToSlide(this.currentIndex + 1);
  }

  /**
   * 切换到上一张轮播项
   */
  public prev(): void {
    let prevIndex = this.currentIndex - 1;

    if (prevIndex < 0) {
      prevIndex = this.totalItems - 1;
      this.wrapper!.style.transition = "none";
      this.wrapper!.style.transform = `translateX(-${
        this.totalItems * ((100 / this.wrapperWidthPercent) * 100)
      }%)`;
      void this.wrapper!.offsetWidth;
      this.wrapper!.style.transition = `transform ${this.options.transitionDuration}ms ease-in-out`;
    }

    this.goToSlide(prevIndex);
  }

  /**
   * 启动自动播放功能
   */
  public startAutoPlay(): void {
    if (this.timer) return;
    this.timer = window.setInterval(() => this.next(), this.options.interval);
  }

  /**
   * 停止自动播放功能
   */
  public stopAutoPlay(): void {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  }

  /**
   * 销毁轮播图实例
   */
  public destroy(): void {
    this.stopAutoPlay();
    // TODO: 清理事件监听器和其他资源
  }
}

// 导出轮播图主类
export default CarouselChart;

/**
 * 便捷创建轮播图的工厂函数
 */
export function createCarousel(
  containerSelector: string,
  itemsSelector: string
): CarouselChart {
  return new CarouselChart({
    container: containerSelector,
    items: itemsSelector,
    autoPlay: true,
    interval: 3000,
    showDots: true,
    showArrows: true,
    transitionDuration: 500,
  });
}
